package com.example.controller.auth;

import com.example.entity.RestBean;
import com.example.entity.vo.request.auth.EmailRegisterVO;
import com.example.entity.vo.request.auth.EmailResetVO;
import com.example.entity.vo.request.auth.ResetConfirmVO;
import com.example.service.AccountService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 授权相关控制器，用于处理用户认证过程中的辅助操作
 *
 * @auth shanyue
 * @date 2025年06月23日10:29
 */
@RestController
@RequestMapping("/api/auth")
@Validated
public class AuthorizeController {

    @Resource
    private AccountService accountService;

    /**
     * 获取邮箱验证码接口
     * 根据邮箱和验证码类型发送验证码，限制请求频率以防止刷接口
     *
     * @param email   目标邮箱地址，用于接收验证码
     * @param type    验证码类型，注册所需或重置密码所需
     * @param request 当前HTTP请求对象，用于获取请求方IP地址
     * @return 返回统一的成功或失败信息
     */
    @GetMapping("/ask-code")
    public RestBean<Void> asVerifyCode(
            @RequestParam @Email String email,
            @RequestParam @Pattern(regexp = "(register|reset)") String type,
            HttpServletRequest request) {
        System.out.println("请求获取验证码，邮箱: " + email + ", 类型: " + type);
        return this.messageHandle(() -> accountService.registerEmailVerifyCode(type, email, request.getRemoteAddr()));
    }

    /**
     * 邮箱注册接口
     * 用户通过邮箱注册账号
     *
     * @param registerVO 封装注册请求参数的对象
     * @return 返回统一的成功或失败信息
     */
    @PostMapping("/register")
    public RestBean<Void> register(@RequestBody @Valid EmailRegisterVO registerVO) {
        System.out.println("接收到的注册请求: " + registerVO);
        String result = accountService.registerEmailAccount(registerVO);
        System.out.println("注册返回结果: " + result);  // 打印注册返回结果
        // 使用 Supplier 包装 result
        return this.messageHandle(() -> result);  // 这里传入一个 Supplier<String>
    }

    /**
     * 验证重置验证码是否正确
     *
     * @param resetConfirmVO 验证码确认请求体，包含邮箱和验证码
     * @return 返回统一成功或失败信息
     */
    @PostMapping("/reset-confirm")
    public RestBean<Void> resetConfirm(@RequestBody @Valid ResetConfirmVO resetConfirmVO) {
        System.out.println("验证码确认请求：邮箱: " + resetConfirmVO.getEmail() + ", 验证码: " + resetConfirmVO.getCode());
        return this.messageHandle(resetConfirmVO, accountService::resetConfirm);
    }

    /**
     * 重置密码接口
     *
     * @param emailResetVO 重置密码请求体，包含邮箱、验证码、新密码
     * @return 返回统一成功或失败信息
     */
    @PostMapping("/reset-password")
    public RestBean<Void> resetConfirm(@RequestBody @Valid EmailResetVO emailResetVO) {
        System.out.println("密码重置请求：邮箱: " + emailResetVO.getEmail());
        return this.messageHandle(emailResetVO, accountService::resetEmailAccountPassword);
    }

    @GetMapping("/getAccountCount")
    public RestBean<Integer> getAccountCount(){
        System.out.println("用户数量为" + accountService.getAccountCount());
        return RestBean.success(accountService.getAccountCount());
    }

    /**
     * 泛型通用请求处理方法(带参)
     *
     * @param vo       请求对象
     * @param function 业务逻辑处理函数,返回null为成功
     * @param <T>      请求参数类型
     * @return 返回统一成功或失败信息
     */
    private <T> RestBean<Void> messageHandle(T vo, Function<T, String> function) {
        return messageHandle(() -> function.apply(vo));
    }

    /**
     * 通用响应封装方法(无参)
     * 执行传入的业务操作，并根据结果构造统一响应结构
     *
     * @param action 可执行的操作，null表示成功
     * @return 封装后的响应体，200为成功，400为失败
     */
    private RestBean<Void> messageHandle(Supplier<String> action) {
        String message = action.get();
        System.out.println("执行的操作结果: " + message);
        return message == null ? RestBean.success() : RestBean.failure(400, message);
    }

}
